/*
 * Copyright (c) 2024-2025.  little3201.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.leafage.exploiter.controller;

import io.leafage.exploiter.dto.ScriptDTO;
import io.leafage.exploiter.service.ScriptService;
import io.leafage.exploiter.vo.ScriptVO;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/scripts")
public class ScriptController {

    private final Logger logger = LoggerFactory.getLogger(ScriptController.class);

    private final ScriptService scriptService;

    /**
     * Constructor for Controller.
     *
     * @param scriptService a {@link ScriptService} object
     */
    public ScriptController(ScriptService scriptService) {
        this.scriptService = scriptService;
    }

    /**
     * Retrieves a list of records filtered by name.
     *
     * @param name The name filter for the records.
     * @return A list of records, or 204 status code if an error occurs.
     */
    @PreAuthorize("hasAuthority('SCOPE_scripts:read')")
    @GetMapping
    public ResponseEntity<List<ScriptVO>> retrieve(String name) {
        List<ScriptVO> voList;
        try {
            voList = scriptService.retrieve(name);
        } catch (Exception e) {
            logger.error("Retrieve script error: ", e);
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.ok(voList);
    }

    /**
     * Fetches a record by ID.
     *
     * @param id The record ID.
     * @return The record data, or 204 status code if an error occurs.
     */
    @PreAuthorize("hasAuthority('SCOPE_scripts:read')")
    @GetMapping("/{id}")
    public ResponseEntity<ScriptVO> fetch(@PathVariable Long id) {
        ScriptVO vo;
        try {
            vo = scriptService.fetch(id);
        } catch (Exception e) {
            logger.error("Fetch script error: ", e);
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.ok(vo);
    }

    /**
     * Creates a new record.
     *
     * @param dto The record data transfer object.
     * @return The created record, or 417 status code if an error occurs.
     */
    @PreAuthorize("hasAuthority('SCOPE_scripts:create')")
    @PostMapping
    public ResponseEntity<ScriptVO> create(@RequestBody @Valid ScriptDTO dto) {
        ScriptVO vo;
        try {
            vo = scriptService.create(dto);
        } catch (Exception e) {
            logger.error("Create script error: ", e);
            return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).build();
        }
        return ResponseEntity.status(HttpStatus.CREATED).body(vo);
    }

    /**
     * Removes a record by ID.
     *
     * @param id The record ID.
     * @return 200 status code if successful, or 417 status code if an error occurs.
     */
    @PreAuthorize("hasAuthority('SCOPE_scripts:modify')")
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> remove(@PathVariable Long id) {
        try {
            scriptService.remove(id);
        } catch (Exception e) {
            logger.error("Remove script error: ", e);
            return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).build();
        }
        return ResponseEntity.ok().build();
    }

}
